﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lt.Engine;
using Lt.Engine.Library;
using Lt.Engine.Scene;
using Lt.Engine.Types;
using RayDen.Library.Core;
using RayDen.Library.Core.Components;
using RayDen.Library.Core.Primitives;
using RayDen.RayEngine.Core.Interface;

namespace Lt.Managers
{
    public class SceneManager
    {
        private LtScene scene;
        HashSet<int> lightIndex;
        HashSet<int> volumeIndex;

        public SceneManager(LtScene scene)
        {
            this.scene = scene;
            lightIndex = new HashSet<int>();
            volumeIndex = new HashSet<int>();
            foreach (var intersectable in scene.Intersectables)
            {
                if (intersectable is LtLightsource)
                {
                    var lt = (intersectable as LtLightsource);
                    //if (lt.Entity is AreaLightsource) lightIndex.Add()
                }
            }
        }

        public LtGeoObject GetObjectByTriangleIndex(int currentTriangleIndex)
        {
            var mesh = scene.sceneData.GetMeshByTriangleIndex(currentTriangleIndex);
            foreach (var intersectable in scene.Geometry)
            {
                if (intersectable.Entity.MeshName.Equals(mesh.MeshName, StringComparison.InvariantCultureIgnoreCase)) // TODO Compare references
                    return intersectable;
            }
            return null;
        }

        public RayIntersection EvalIntersection(RayDifferential ray, ref RayHit rh, RayIntersection isect)
        {
            var ii = isect ?? (isect = new RayIntersection());
            var currentTriangleIndex = (int) rh.Index;

            var obj = GetObjectByTriangleIndex(currentTriangleIndex);
            ii.Hitpoint = ray.Point(rh.Distance);
            ii.BaryCentricPoint = new UV(rh.U, rh.V);
            

            obj.Entity.InterpolateTriangleNormal(currentTriangleIndex, rh.U, rh.V, ref ii.ShadingNormal);
            obj.Entity.InterpolateTriUV(currentTriangleIndex, rh.U, rh.V, out ii.TextureCoords);

            ii.GeoNormal = scene.sceneData.Triangles[currentTriangleIndex].ComputeNormal(scene.sceneData.GeoData.Vertices);
            ii.ComputeDifferential(ray);

            return ii;
        }
    }
}
